package com.chapter_6;

/**
 * @Author: Timo
 * @Date: 2019/5/16 11:58
 * @Description: 提供读写锁的类
 */
public class ReadWriteLock {
    /**
     * (A)...实际正在读取中的线程个数
     */
    private int readingReaders = 0;
    /**
     * (B)...正在等待写入的线程个数
     */
    private int waitingWriters = 0;
    /**
     * (C)...实际正在写入中的线程个数
     */
    private int writingWriters = 0;
    /**
     * (D)...如果写入优先，则为true/否则false
     */
    private boolean preferWriter = true;

    /**
     * 获取读锁
     *
     * @throws InterruptedException
     */
    public synchronized void readLock() throws InterruptedException {
        while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
            wait();
        }
        readingReaders++;                       // (A) 实际正在读取的线程个数加1
    }

    /**
     * 释放读锁
     */
    public synchronized void readUnLock() {
        readingReaders--;                       // (A) 实际正在读取的线程个数减1
        preferWriter = true;
        notifyAll();
    }

    /**
     * 获取写入的锁
     *
     * @throws InterruptedException
     */
    public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;                       // (B) 正在等待写入的线程个数加1
        try {

            while (readingReaders > 0 || writingWriters > 0) {
                System.out.println(Thread.currentThread().getName() + " readingReaders : "+ readingReaders + " writingWriters : "+ writingWriters + " 继续等待...");
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            waitingWriters--;                   // (B) 正在等待写入的线程个数减1
        }
        writingWriters++;                       // (C) 实际正在写入的线程个数加1
        System.out.println(Thread.currentThread().getName() + " 等待结束.... 开始写入 ... ");
    }

    /**
     * 释放写入的锁
     */
    public synchronized void writeUnLock() {
        writingWriters--;                       // (C) 实际正在写入的线程个数减1
        preferWriter = false;
        notifyAll();
    }
}
